namespace PickGold.Charting
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;

    internal class RingTimeTracker
    {
        private LinkedListNode<RingItem> _current;
        private TimeSpan _itemLifeTime = TimeSpan.FromSeconds(360.0);
        private string _keyFormat = string.Empty;
        private LinkedList<RingItem> _list = new LinkedList<RingItem>();
        private bool _recordSessionID;

        internal RingTimeTracker(TimeSpan itemLifeTime, string keyFormat, bool recordSessionID)
        {
            this._itemLifeTime = itemLifeTime;
            this._keyFormat = keyFormat;
            this._list.AddLast(new RingItem(this._list.Count));
            this._current = this._list.First;
            this._current.Value.Created = (DateTime.Now - this._itemLifeTime) - TimeSpan.FromSeconds(1.0);
            this._recordSessionID = recordSessionID;
        }

        public void ForEach(bool onlyExpired, Action<RingItem> action)
        {
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }
            DateTime now = DateTime.Now;
            lock (this)
            {
                foreach (RingItem item in this._list)
                {
                    if (onlyExpired)
                    {
                        if (this.IsExpired(item, now))
                        {
                            action(item);
                        }
                    }
                    else
                    {
                        action(item);
                    }
                }
            }
        }

        internal string GetCurrentKey()
        {
            return string.Format(CultureInfo.InvariantCulture, this._keyFormat, new object[] { this._current.Value.Index });
        }

        internal string GetKey(RingItem ringItem)
        {
            return string.Format(CultureInfo.InvariantCulture, this._keyFormat, new object[] { ringItem.Index });
        }

        internal string GetNextKey()
        {
            DateTime now = DateTime.Now;
            lock (this)
            {
                if (!this.IsExpired(this._current.Value, now))
                {
                    if (this._current.Next == null)
                    {
                        if (!this.IsExpired(this._list.First.Value, now))
                        {
                            this._list.AddLast(new RingItem(this._list.Count));
                            this._current = this._list.Last;
                        }
                        else
                        {
                            this._current = this._list.First;
                        }
                    }
                    else
                    {
                        if (!this.IsExpired(this._current.Next.Value, now))
                        {
                            this._list.AddAfter(this._current, new RingItem(this._list.Count));
                        }
                        this._current = this._current.Next;
                    }
                }
                this._current.Value.Created = now;
                if (this._recordSessionID)
                {
                    this._current.Value.SessionID = ChartHttpHandler.Settings.SessionID;
                    this._current.Value.InUse = true;
                }
                return this.GetCurrentKey();
            }
        }

        internal bool IsExpired(RingItem item, DateTime now)
        {
            TimeSpan span = (TimeSpan) (now - item.Created);
            return (span > this._itemLifeTime);
        }
    }
}

